added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2008 / CppAutomateVisio / Solution2.cpp
blob0821e7f9243e1947df4ec5650d1d20fcb2c19791
1 /****************************** Module Header ******************************\
2 * Module Name: Solution2.cpp
3 * Project: CppAutomateVisio
4 * Copyright (c) Microsoft Corporation.
5 *
6 * The code in Solution2.h/cpp demontrates the use of C/C++ and the COM APIs
7 * to automate Visio. The raw automation is much more difficult, but it is
8 * sometimes necessary to avoid the overhead with MFC, or problems with
9 * #import. Basically, you work with such APIs as CoCreateInstance(), and COM
10 * interfaces such as IDispatch and IUnknown.
12 * This source is subject to the Microsoft Public License.
13 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
14 * All other rights reserved.
16 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
17 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
19 \***************************************************************************/
21 #pragma region Includes
22 #include "stdafx.h"
23 #include "Solution2.h"
24 #pragma endregion
27 DWORD WINAPI AutomateVisioByCOMAPI(LPVOID lpParam)
29 HRESULT hr;
31 // Initializes the COM library on the current thread and identifies
32 // the concurrency model as single-thread apartment (STA).
33 // [-or-] ::CoInitialize(NULL);
34 // [-or-] ::CoCreateInstance(NULL);
35 ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
38 /////////////////////////////////////////////////////////////////////////
39 // Create the Visio.Application COM object using C++ and COM APIs.
40 //
42 // Get CLSID of the server
44 CLSID clsid;
46 // Option 1. Get CLSID from ProgID using CLSIDFromProgID.
47 LPCOLESTR progID = L"Visio.Application";
48 hr = ::CLSIDFromProgID(progID, &clsid);
49 if (FAILED(hr))
51 wprintf(L"CLSIDFromProgID(\"%s\") failed w/err 0x%08lx\n", progID, hr);
52 return hr;
54 // Option 2. Build the CLSID directly.
55 /*const IID CLSID_Application =
56 {0x00021A20,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
57 clsid = CLSID_Application;*/
59 // Start the server and get the IDispatch interface
61 IDispatch* pVisioApp = NULL;
62 hr = CoCreateInstance( // [-or-] CoCreateInstanceEx, CoGetObject
63 clsid, // CLSID of the server
64 NULL,
65 CLSCTX_LOCAL_SERVER, // Visio.Application is a local server
66 IID_IDispatch, // Query the IDispatch interface
67 (void **)&pVisioApp); // Output
69 if (FAILED(hr))
71 _tprintf(_T("Visio is not registered properly w/err 0x%08lx\n"),
72 hr);
73 return hr;
76 _putts(_T("Visio.Application is started"));
79 /////////////////////////////////////////////////////////////////////////
80 // Make Visio invisible. (Application.Visible = 0)
81 //
84 VARIANT x;
85 x.vt = VT_I4;
86 x.lVal = 0;
87 hr = AutoWrap(DISPATCH_PROPERTYPUT, NULL, pVisioApp, L"Visible", 1, x);
91 /////////////////////////////////////////////////////////////////////////
92 // Create a new Document based on no template.
93 // (i.e. Application.Documents.Add(""))
94 //
96 // Get the Documents collection
97 IDispatch* pDocs = NULL;
99 VARIANT result;
100 VariantInit(&result);
101 hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pVisioApp, L"Documents", 0);
102 pDocs = result.pdispVal;
105 // Call Documents.Add("") to get a new document based on no template
106 IDispatch* pDoc = NULL;
108 VARIANT x;
109 x.vt = VT_BSTR;
110 x.bstrVal = ::SysAllocString(L"");
112 VARIANT result;
113 VariantInit(&result);
114 hr = AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Add", 1, x);
115 pDoc = result.pdispVal;
117 VariantClear(&x);
120 _putts(_T("A new document is created"));
123 /////////////////////////////////////////////////////////////////////////
124 // Draw a rectangle and a oval on the first page.
127 _putts(_T("Draw a rectangle and a oval"));
129 // Get the Pages collection
130 IDispatch* pPages = NULL;
132 VARIANT result;
133 VariantInit(&result);
134 hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, L"Pages", 0);
135 pPages = result.pdispVal;
138 // Get the first page (pPages->Item[1])
139 IDispatch* pPage = NULL;
141 VARIANT x;
142 x.vt = VT_I4;
143 x.lVal = 1;
145 VARIANT result;
146 VariantInit(&result);
147 hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pPages, L"Item", 1, x);
148 pPage = result.pdispVal;
151 // Draw a rectangle (pPage->DrawRectangle)
152 IDispatch* pRectShape = NULL;
154 VARIANT x1;
155 x1.vt = VT_R8;
156 x1.dblVal = 0.5;
157 VARIANT y1;
158 y1.vt = VT_R8;
159 y1.dblVal = 10.25;
160 VARIANT x2;
161 x2.vt = VT_R8;
162 x2.dblVal = 6.25;
163 VARIANT y2;
164 y2.vt = VT_R8;
165 y2.dblVal = 7.375;
167 VARIANT result;
168 VariantInit(&result);
169 hr = AutoWrap(DISPATCH_METHOD, &result, pPage, L"DrawRectangle",
170 4, y2, x2, y1, x1);
171 pRectShape = result.pdispVal;
174 // Draw a oval (pPage->DrawOval)
175 IDispatch* pOvalShape = NULL;
177 VARIANT x1;
178 x1.vt = VT_R8;
179 x1.dblVal = 1.125;
180 VARIANT y1;
181 y1.vt = VT_R8;
182 y1.dblVal = 6;
183 VARIANT x2;
184 x2.vt = VT_R8;
185 x2.dblVal = 6.875;
186 VARIANT y2;
187 y2.vt = VT_R8;
188 y2.dblVal = 2.125;
190 VARIANT result;
191 VariantInit(&result);
192 hr = AutoWrap(DISPATCH_METHOD, &result, pPage, L"DrawOval",
193 4, y2, x2, y1, x1);
194 pOvalShape = result.pdispVal;
198 /////////////////////////////////////////////////////////////////////
199 // Save the document as a vsd file and close it.
202 _putts(_T("Save and close the document"));
204 // pDoc->SaveAs
206 // Make the file name
208 // Get the directory of the current exe.
209 WCHAR szFileName[MAX_PATH];
210 if (FAILED(GetModuleDirectoryW(szFileName, MAX_PATH)))
212 _putts(_T("GetModuleDirectoryW failed"));
213 return S_FALSE;
216 // Concat "Sample2.vsd" to the directory
217 wcsncat_s(szFileName, MAX_PATH, L"Sample2.vsd", 11);
219 // Convert the NULL-terminated string to BSTR
220 VARIANT vtFileName;
221 vtFileName.vt = VT_BSTR;
222 vtFileName.bstrVal = ::SysAllocString(szFileName);
224 hr = AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"SaveAs", 1, vtFileName);
226 VariantClear(&vtFileName);
229 // pDoc->Close()
230 hr = AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 0);
233 /////////////////////////////////////////////////////////////////////////
234 // Quit the Visio application. (i.e. Application.Quit())
237 _putts(_T("Quit the Visio application"));
238 hr = AutoWrap(DISPATCH_METHOD, NULL, pVisioApp, L"Quit", 0);
241 /////////////////////////////////////////////////////////////////////////
242 // Release the COM objects.
245 if (pOvalShape != NULL)
247 pOvalShape->Release();
249 if (pRectShape != NULL)
251 pRectShape->Release();
253 if (pPage != NULL)
255 pPage->Release();
257 if (pPages != NULL)
259 pPages->Release();
261 if (pDoc != NULL)
263 pDoc->Release();
265 if (pDocs != NULL)
267 pDocs->Release();
269 if (pVisioApp != NULL)
271 pVisioApp->Release();
274 // Uninitialize COM for this thread
275 ::CoUninitialize();
277 return hr;
282 * \brief
283 * The definition of AutoWrap in the header file
285 * \see
286 * Separate Solution2.h | AutoWrap
288 HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
289 LPOLESTR ptName, int cArgs...)
291 // Begin variable-argument list
292 va_list marker;
293 va_start(marker, cArgs);
295 if (!pDisp)
297 _putts(_T("NULL IDispatch passed to AutoWrap()"));
298 return E_INVALIDARG;
301 // Variables used
302 DISPPARAMS dp = { NULL, NULL, 0, 0 };
303 DISPID dispidNamed = DISPID_PROPERTYPUT;
304 DISPID dispID;
305 HRESULT hr;
307 // Get DISPID for name passed
308 hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
309 if (FAILED(hr))
311 wprintf(L"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n",
312 ptName, hr);
313 return hr;
316 // Allocate memory for arguments
317 VARIANT *pArgs = new VARIANT[cArgs + 1];
318 // Extract arguments...
319 for(int i=0; i < cArgs; i++)
321 pArgs[i] = va_arg(marker, VARIANT);
324 // Build DISPPARAMS
325 dp.cArgs = cArgs;
326 dp.rgvarg = pArgs;
328 // Handle special-case for property-puts
329 if (autoType & DISPATCH_PROPERTYPUT)
331 dp.cNamedArgs = 1;
332 dp.rgdispidNamedArgs = &dispidNamed;
335 // Make the call
336 hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
337 autoType, &dp, pvResult, NULL, NULL);
338 if (FAILED(hr))
340 wprintf(L"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n",
341 ptName, dispID, hr);
342 return hr;
345 // End variable-argument section
346 va_end(marker);
348 delete[] pArgs;
350 return hr;